﻿using UnityEngine;
using System.Collections;
using NetFramework;
using System.Collections.Generic;
using System;
using System.Net.Sockets;

public class ConnectedResult
{
    public bool beResult = false;
    public string message = "";
}

public class NetHelper : MonoBehaviour {

    public delegate void OnEventReceiveDelgate(Dictionary<string,object> message);

    private static NetHelper m_instance;
    private TSocketClient m_client;
    private Action<bool,string> m_connectResult;
    ConnectedResult m_connectedInfo = null;
    Dictionary<string, List<OnEventReceiveDelgate>> m_eventHander = new Dictionary<string, List<OnEventReceiveDelgate>>();

    private List<string> m_message = new List<string>();

    public static NetHelper Instance
    {
        get 
        {
            if (m_instance == null)
            {
                GameObject go = new GameObject();
                go.name = "NetHelper";
                m_instance = go.AddComponent<NetHelper>();
                GameObject.DontDestroyOnLoad(go);
            }
            return NetHelper.m_instance; 
        }
    }

    public static void RegisterEvent(string route,OnEventReceiveDelgate receive)
    {
        Instance.ClientRegisterEvent(route, receive);
    }

    public static void RemoveEvent(string route, OnEventReceiveDelgate receive)
    {
        Instance.ClientRemoveEvent(route, receive);
    }


    public static void RemoveAllEvent()
    {
        m_instance.m_eventHander.Clear();
    }
    private void ClientRegisterEvent(string route, OnEventReceiveDelgate receive)
    {
        List<OnEventReceiveDelgate> lst = null;
        if (!m_eventHander.TryGetValue(route, out lst))
        {
            lst = new List<OnEventReceiveDelgate>();
            m_eventHander[route] = lst;
        }
        if (lst.IndexOf(receive) == -1)
        {
            lst.Add(receive);
        }
    }

    private void ClientRemoveEvent(string route, OnEventReceiveDelgate receive)
    {
        List<OnEventReceiveDelgate> lst = null;
        if (!m_eventHander.TryGetValue(route, out lst))
        {
            return;
        }
        if (lst.IndexOf(receive) != -1)
        {
            lst.Remove(receive);
        }
    }



    public void ClientConnect(string ip, int port, Action<bool, string> fun)
    {
        m_client = new TSocketClient();
        m_client.OnConnected += c_OnConnected;
        m_client.OnError += m_client_OnError;
        m_client.ReceivedDatagram += c_ReceivedDatagram;
        m_client.OnDisconnected += m_client_OnDisconnected; 
        m_client.Connect(ip, port);

        m_connectResult = fun;
    }

    public void ClientDisConnect()
    {
        try
        {
            m_client.Disconnect();
        }
        catch (Exception e)
        {

        }
    }

    void m_client_OnError(object sender, TSocketClientErrorEventArgs e)
    {
        
        if ((SocketError)e.exception.ErrorCode == SocketError.ConnectionRefused)
        {
            if (m_connectResult != null)
            {
                m_connectedInfo = new ConnectedResult();
                m_connectedInfo.beResult = false;
                m_connectedInfo.message = "服务器连接失败";
            }
        }
        else
        {
            Debug.LogError(e.exception.Message);
        }
    }

    void m_client_OnDisconnected(object sender, TSocketClientConnectedEventArgs e)
    {
        m_connectedInfo = new ConnectedResult();
        m_connectedInfo.beResult = false;
        m_connectedInfo.message = "服务器连接失败";
        Debug.LogError("DissConnected!!!!!!!!!!!!!!!!!!");
    }

    private void c_ReceivedDatagram(object sender, TSocketClientDataInEventArgs e)
    {
        try
        {
            string message = System.Text.Encoding.UTF8.GetString(e.Data);
            //Console.WriteLine(message);
            lock (m_message)
            {
                m_message.Add(message);
            }
            
        }
        catch (Exception ex)
        {

            Console.WriteLine(ex.ToString());
        }
    }

    private void DealMessage(string message){
        Debug.LogError(message);
        Dictionary<string, object> dic = Json.Deserialize(message) as Dictionary<string, object>;
        if (dic != null)
        {
            string route = dic["route"].ToString();

            List<OnEventReceiveDelgate> lst = null;
            if (m_eventHander.TryGetValue(route, out lst))
            {
                foreach (OnEventReceiveDelgate eve in lst)
                {
                    try
                    {
                        eve(dic);
                    }
                    catch(Exception e)
                    {
                        Debug.Log(e.Message);
                    }  
                }
            }
        }

        m_message.Remove(message);
    }

    void c_OnConnected(object sender, TSocketClientConnectedEventArgs e)
    {
        if (m_connectResult != null)
        {
            m_connectedInfo = new ConnectedResult();
            m_connectedInfo.beResult = true;
            m_connectedInfo.message = "connect success";
        }
        
    }

    /// <summary>
    /// 连接服务器
    /// </summary>
    /// <param name="ip"></param>
    /// <param name="port"></param>
    /// <param name="fun"></param>
    public static void Connect(string ip, int port, Action<bool, string> fun)
    {
        Instance.ClientConnect(ip, port, fun);
    }


    public static void Send(string route,Dictionary<string, object> message)
    {
        Instance.ClientSend(route, message);
    }

    /// <summary>
    /// 发送报文消息
    /// </summary>
    /// <param name="route"></param>
    /// <param name="message"></param>
    public void ClientSend(string route, Dictionary<string, object> message)
    {
        message["route"] = route;
        string s = Json.Serialize(message);
        Debug.Log("send   " + s);
        byte[] bytess = System.Text.Encoding.UTF8.GetBytes(s);
        m_client.Send(bytess);
    }


    void Update()
    {
        if (m_connectedInfo != null)
        {
            try
            {
                m_connectResult(m_connectedInfo.beResult, m_connectedInfo.message);
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
            
            m_connectedInfo = null;
        }

        if(m_message.Count > 0)
        {
            lock (m_message)
            {
                for (int index = m_message.Count - 1; index >= 0; index--)
                {
                    DealMessage(m_message[index]);
                }

                m_message.Clear();
            }
        }
    }

    void OnDestroy()
    {
        try
        {
            ClientDisConnect();
        }
        catch (Exception e) { }
        
    }
}
